/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.controller.excel;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.je.common.base.DynaBean;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mvc.AbstractPlatformController;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.redis.service.RedisCache;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.result.DirectJsonResult;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.util.*;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.rpc.excel.ExcelRpcService;
import com.je.meta.service.ExcelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * @program: jecloud-meta
 * @author: LIULJ
 * @create: 2021-08-03 19:34
 * @description:
 */
@RestController
@RequestMapping(value = "/je/meta/excel")
public class ExcelController extends AbstractPlatformController {

    private static final String EXCEL_DOWNLOAD_KEY = "excelDownloadKeys";
    private static final long EXCEL_DOWNLOAD_KEY_TIMEOUT = 100000;

    @Autowired
    private ExcelService excelService;
    @Autowired
    private ExcelRpcService excelRpcService;
    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private Environment environment;

    @RequestMapping(value = "/downloadKey", method = RequestMethod.POST)
    public BaseRespResult downloadKey(BaseMethodArgument param, HttpServletRequest request) throws UnsupportedEncodingException {
        //获取全部参数
        String dataStr = getStringParameter(request, "data");
        if (StringUtil.isEmpty(dataStr)) {
            return BaseRespResult.errorResult("参数格式错误...");
        }
        //base64转码
        /*dataStr = URLDecoder.decode(URLDecoder.decode(Base64.decodeStr(dataStr),"UTF-8"),"UTF-8");*/
        String key = JEUUID.uuid();
        redisCache.put(String.format("%s_%s", EXCEL_DOWNLOAD_KEY, key), dataStr, EXCEL_DOWNLOAD_KEY_TIMEOUT);
        return BaseRespResult.successResult(key, "缓存成功！");
    }


    /**
     * 表格数据导出
     *
     * @param param
     */
    @RequestMapping(value = "/exp", method = RequestMethod.GET)
    public File exp(BaseMethodArgument param, HttpServletRequest request) {
        //获取全部参数
        String key = getStringParameter(request, "key");
        key = String.format("%s_%s", EXCEL_DOWNLOAD_KEY, key);
        String dataStr = (String) redisCache.get(key);
        //列表样式导出，当前数据
        //dataStr = "{\"title\":\"测试导出列\",\"fileName\":\"测试导出_2022-04-14.xlsx\",\"orderSql\":\"\",\"docFolderId\":\"\",\"funcId\":\"296fabef-573a-4953-bfbe-aca2f1864a20\",\"tableCode\":\"JE_CORE_TABLECOLUMN\",\"funcCode\":\"\",\"whereSql\":\"\",\"j_query\":{\"custom\":[{\"type\":\"in\",\"code\":\"JE_CORE_TABLECOLUMN_ID\",\"value\":[\"de14046d33254279b262b2ca72b7dee5\",\"07c86e3cccbf4f539f4f1689c536fc5d\"]}]},\"styleType\":\"GRID\"}";
        //dataStr ="{\"title\":\"测试模板导出\",\"fileName\":\"测试模板导出_2022-04-16.xlsx\",\"orderSql\":\" \",\"docFolderId\":\"\",\"funcId\":\"lKS0sRAb1RxcsVAWstd\",\"tableCode\":\"JE_META_TABLE2\",\"funcCode\":\"JE_META_TABLE2\",\"whereSql\":\" AND JE_META_TABLE2_ID IN ('1','2')\",\"j_query\":{\"custom\":[{\"type\":\"in\",\"code\":\"JE_META_TABLE2_ID\",\"value\":['1','2']}]},\"styleType\":\"TEMPLATE\",\"sheetId\":\"ab6da4f70a294e09aa3467c5179fdb4a\"}";
        //获取参数集
        JSONObject params = JSONObject.parseObject(dataStr);
        String tableCode = params.getString("tableCode");
        String funcId = params.getString("funcId");
        String fileName = params.getString("fileName");
        String queryType = params.getString("queryType");
        String procedureName = params.getString("procedureName");
        String dbSql = params.getString("dbSql");

        if ("procedure".equals(queryType) || "iditprocedure".equals(queryType)) {
            if (StringUtil.isEmpty(procedureName) || StringUtil.isEmpty(funcId)) {
                throw new PlatformException("存储过程名未传入", PlatformExceptionEnum.JE_CORE_EXCEL_PROCEDURE_ERROR, request);
            }
        } else if ("sql".equals(queryType)) {
            if (StringUtil.isEmpty(dbSql) || StringUtil.isEmpty(funcId)) {
                throw new PlatformException("自定义sql未传入", PlatformExceptionEnum.JE_CORE_EXCEL_DIYSQL_ERROR, request);
            }
        } else {
            if (StringUtil.isEmpty(tableCode) || StringUtil.isEmpty(funcId)) {
                throw new PlatformException("功能表名未传入", PlatformExceptionEnum.JE_CORE_EXCEL_TABLECODE_ERROR, request);
            }
        }

        try {
            //导出Excel
            InputStream inputStream = excelService.exportExcel(params, request);
            String defaultDirectory = environment.getProperty("servicecomb.downloads.directory");
            FileUtil.writeFromStream(inputStream, defaultDirectory + File.separator + fileName);
            return new File(defaultDirectory + File.separator + fileName);
        } catch (Exception e) {
            throw new PlatformException("新版导出Excel出错了", PlatformExceptionEnum.JE_CORE_EXCEL_EXP_ERROR, request, e);
        }
    }

    /**
     * 获取功能对应的Excel模板
     *
     * @param param
     */
    @RequestMapping(value = "/exp/template", method = RequestMethod.POST)
    public BaseRespResult funcTemplateList(BaseMethodArgument param, HttpServletRequest request) {
        try {
            //获取功能ID
            String funcId = getStringParameter(request, "funcId");
            if (StringUtil.isEmpty(funcId)) {
                throw new PlatformException("参数为空", PlatformExceptionEnum.JE_CORE_EXCEL_EXP_ERROR, request);
            }
            //查询模板文件
            List<Map<String, Object>> sheets = excelRpcService.funcTemplateList(funcId);
            return BaseRespResult.successResult(sheets);
        } catch (PlatformException e) {
            throw e;
        } catch (Exception e) {
            throw new PlatformException("获取功能Excel模板异常", PlatformExceptionEnum.JE_CORE_EXCEL_EXP_ERROR, request, e);
        }
    }

    /**
     * 数据导入窗口(第一次上传文件)
     *
     * @param param
     */
    @RequestMapping(value = "/doSave", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @Override
    public BaseRespResult doSave(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        String fileValue = dynaBean.getStr("GROUPTEM_FILE");
        if (StringUtil.isNotEmpty(fileValue)) {
            String fileKey = fileValue.split("\\*")[1];
            try {
                excelService.impData(dynaBean, fileKey, request);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 删除文件
            documentInternalRpcService.delFilesByKey(Lists.newArrayList(fileKey), SecurityUserHolder.getCurrentAccountRealUserId());
        }
        //返回给前台
        return BaseRespResult.successResult(dynaBean);
    }

    /**
     * 数据导入窗口(修改文件重新上传)
     *
     * @param param
     */
    @RequestMapping(value = "/doUpdate", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @Override
    public BaseRespResult doUpdate(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        String funcCode = param.getFuncCode();
        //构建修改信息
        commonService.buildModelModifyInfo(dynaBean);
        //更新数据
        metaService.update(dynaBean);
        String fileValue = dynaBean.getStr("GROUPTEM_FILE");
        if (StringUtil.isNotEmpty(fileValue)) {
            String fileKey = fileValue.split("\\*")[1];
            try {
                excelService.impData(dynaBean, fileKey, request);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 删除文件
            documentInternalRpcService.delFilesByKey(Lists.newArrayList(fileKey), SecurityUserHolder.getCurrentAccountRealUserId());
        }
        //如果表单内有附件则查询出新的数据返回
        return BaseRespResult.successResult(dynaBean);
    }

    /**
     * 数据预处理
     */
    @RequestMapping(value = "/doPreviewData", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doPreviewData(HttpServletRequest request) {
        String groupCode = getStringParameter(request, "groupCode");
        String temGroupId = getStringParameter(request, "temGroupId");
        String temIds = getStringParameter(request, "temIds");

        if (StringUtil.isEmpty(temIds) && StringUtil.isNotEmpty(temGroupId)) {
            List<DynaBean> temConfigs = metaService.select("JE_EXCEL_CONFIGTEMP", ConditionsWrapper.builder().eq("JE_EXCEL_GROUPTEM_ID", temGroupId));
            temIds = StringUtil.buildSplitString(ArrayUtils.getBeanFieldArray(temConfigs, "JE_EXCEL_CONFIGTEMP_ID"), ",");
        }

        JSONObject returnObj = new JSONObject();
        excelService.impPreviewData(groupCode, temIds, request, returnObj);
        //处理数据
        if (returnObj.containsKey("error")) {
            return BaseRespResult.errorResult(returnObj.getString("error"));
        } else {
            return BaseRespResult.successResult(returnObj.toString());
        }
    }

    @RequestMapping(value = "/loadSheetInfo", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public JSONArray loadSheetInfo(HttpServletRequest request) {
        String temId = getStringParameter(request, "groupTemId");
        String groupId = getStringParameter(request, "groupId");
        JSONArray arrays = excelRpcService.buildSheetInfo(groupId, temId);
        return DirectJsonResult.buildArrayResult(arrays);
    }

    /**
     * Excel模板文件下载
     * <p>
     * /template?fileKey={fileKey}
     *
     * @param groupCode Excel模板编码
     */
    @RequestMapping(value = {"/template"}, method = RequestMethod.GET)
    public File previewAndDownload(String groupCode) {
        try {
            //查找Excel模板
            DynaBean group = metaService.selectOne("JE_CORE_EXCELGROUP", ConditionsWrapper.builder().apply("GROUPCODE={0}", groupCode));
            if (group == null) {
                throw new PlatformException("模板编码不存在！", PlatformExceptionEnum.UNKOWN_ERROR);
            }
            String fileStr = group.getStr("EXCELGROUP_FILE");
            if (StringUtil.isEmpty(fileStr) || fileStr.split("\\*").length < 2) {
                throw new PlatformException("Excel数据导入模板文件未配置！", PlatformExceptionEnum.UNKOWN_ERROR);
            }
            //用户ID
            String userId = SecurityUserHolder.getCurrentAccountRealUserId();
            //参数验证
            String fileKey = fileStr.split("\\*")[fileStr.split("\\*").length - 1];
            //获取文件信息
            File file = documentInternalRpcService.readFile(fileKey);
            String fileName = URLEncoder.encode(file.getName(), "UTF-8");
            String defaultDirectory = environment.getProperty("servicecomb.downloads.directory");
            FileUtil.writeFromStream(FileUtil.getInputStream(file), defaultDirectory + File.separator + fileName);
            return new File(defaultDirectory + File.separator + fileName);
        } catch (PlatformException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new PlatformException("文件查找错误", PlatformExceptionEnum.UNKOWN_ERROR, e);
        }
    }

    /**
     * 导入字段
     *
     * @param param
     */
    @RequestMapping(value = "implExcelFields", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ResponseBody
    public BaseRespResult implExcelFields(BaseMethodArgument param,HttpServletRequest request) {
        DynaBean dynaBean = new DynaBean();
        dynaBean.setStr("JE_CORE_EXCELSHEET_ID",param.getPkValue());
        dynaBean.setStr("funcId",getStringParameter(request,"funcId"));
        dynaBean.setStr("tableCode",getStringParameter(request,"impTableCode"));
        excelService.implExcelFields(dynaBean);
        return BaseRespResult.successResult(MessageUtils.getMessage("common.import.success"));
    }

    /**
     * 快速规划列
     * @param param
     */
    @RequestMapping(value = "quickColumn", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ResponseBody
    public BaseRespResult quickColumn(BaseMethodArgument param) {
        String pkValue = param.getPkValue();
        if (StringUtil.isNotEmpty(pkValue)) {
            List<DynaBean> fields = metaService.select("JE_CORE_EXCELFIELD",
                    ConditionsWrapper.builder().apply("JE_CORE_EXCELSHEET_ID={0} AND EXCELFIELD_HIDDEN='0' ORDER BY SY_ORDERINDEX", pkValue));
            for (int i = 0; i < fields.size(); i++) {
                DynaBean field = fields.get(i);
                field.set("EXCELFIELD_COLUMN", excelService.getExcelColumnName(i));
                metaService.update(field);
            }
        }
        return BaseRespResult.successResult(MessageUtils.getMessage("common.update.success"));
    }

    /**
     * 清空隐藏
     *
     * @param param
     */
    @RequestMapping(value = "clearExcelHidden", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ResponseBody
    public BaseRespResult clearExcelHidden(BaseMethodArgument param) {
        String pkValue = param.getPkValue();
        if (StringUtil.isNotEmpty(pkValue)) {
            metaService.executeSql("DELETE FROM JE_CORE_EXCELFIELD WHERE JE_CORE_EXCELSHEET_ID={0} AND EXCELFIELD_HIDDEN='1'", pkValue);
            return BaseRespResult.successResult(MessageUtils.getMessage("common.delete.success"));
        } else {
            return BaseRespResult.successResult(MessageUtils.getMessage("common.delete.error"));
        }
    }

}
